package com.xl.studentpass.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xl.studentpass.entity.ImageInfoEntity;
import com.xl.studentpass.entity.OrderInfoEntity;
import com.xl.studentpass.entity.TaskInfoEntity;
import com.xl.studentpass.entity.UserEntity;
import com.xl.studentpass.entity.po.TaskDetailPo;
import com.xl.studentpass.entity.po.TaskOverViewPo;
import com.xl.studentpass.entity.vo.TaskVo;
import com.xl.studentpass.mapper.AcceptTaskMapper;
import com.xl.studentpass.mapper.ImageMapper;
import com.xl.studentpass.mapper.PublishTaskMapper;
import com.xl.studentpass.mapper.UserMapper;
import com.xl.studentpass.service.PublishTaskService;
import com.xl.studentpass.utils.ImageIdType;
import com.xl.studentpass.utils.LocalDateUtils;
import com.xl.studentpass.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.xl.studentpass.service.impl.AcceptTaskServiceImpl.getStrings;
import static com.xl.studentpass.utils.ImageIdType.TASK;
import static com.xl.studentpass.utils.PublicStaticConstant.IS_VALIDITY_ORDER;
import static com.xl.studentpass.utils.TaskOrderStatus.*;

/**
 * @author: xl
 * @createTime: 2023/5/28 15:47:52
 * @program: student-pass
 * @e-mail: 2199396150@qq.com
 * @description:
 */
@Service
@Slf4j
@CacheConfig(cacheNames = "taskInfo")
public class PublishTaskServiceImpl extends ServiceImpl<PublishTaskMapper, TaskInfoEntity> implements PublishTaskService {
    @Resource
    RedisTemplate<String, Object> redisTemplate;
    @Value("${redis.order.key}")
    private String key;
    @Resource
    ImageMapper imageMapper;
    @Resource
    AcceptTaskMapper acceptTaskMapper;
    @Resource
    UserMapper userMapper;
    private final String NAME = this.getClass().getName();

    @Override
    public R create(TaskVo taskVo) {
        try {
            if (ObjectUtils.isEmpty(taskVo.getUserId())) {
                log.error(NAME + "没有用户");
                return R.error("创建任务失败");
            }

            if (checkEmpty(taskVo.getTaskName())) {
                log.error(NAME + "任务名为空");
                return R.error("任务名为空");
            }
            if (checkEmpty(taskVo.getTaskInfo())) {
                log.error(NAME + "任务描述为空");
                return R.error("任务描述为空");
            }

            if (taskVo.getCategoryId() < 0 || taskVo.getCategoryId() > 6) {
                log.error(NAME + "任务分类不符合要求");
                return R.error("任务分类不符合要求");
            }

            if (taskVo.getCategoryId() != 3 && taskVo.getCategoryId() != 4 && taskVo.getCategoryId() != 5) {
                if (ObjectUtils.isEmpty(taskVo.getToPlace()) || ObjectUtils.isEmpty(taskVo.getFromPlace())) {
                    log.error(NAME + "任务地点描述错误");
                    return R.error("任务地点描述错误");
                }
            }

            //Integer userId = taskVo.getUserId();
            //int bUserId = StpUtil.getLoginIdAsInt();
            //
            //if (!userId.equals(bUserId)) {
            //    log.info("登录用户与传入的用户不一样");
            //    return R.error("创建任务失败");
            //}
            TaskInfoEntity taskInfo = new TaskInfoEntity();
            BeanUtil.copyProperties(taskVo, taskInfo);

            //当前时间信息
            String localTime = LocalDateUtils.getLocalDateTimeStr();

            long time = LocalDateUtils.getValidTimeSeconds(localTime, taskInfo.getExpirationTime());
            if (time < 1) {
                log.info("过期时间的秒数" + time);
                return R.error("任务过期时间小于当前时间");
            }
            //设置属性值
            taskInfo.setStatusId(NO_ORDER_RECEIVED.getId());
            taskInfo.setValid(IS_VALIDITY_ORDER);
            taskInfo.setCreateTime(localTime);
            taskInfo.setOperaTime(localTime);

            //扣钱
            UserEntity user = userMapper.selectById(taskVo.getUserId());
            user.setBalance(taskInfo.getTaskPrice());

            //保存到mysql
            int i = userMapper.updateById(user);
            boolean b = this.saveOrUpdate(taskInfo);
            if (i <= 0 || !b) {
                return R.error();
            }

            Integer taskId = taskInfo.getId();

            if (!ObjectUtils.isEmpty(taskVo.getImageIds())) {
                List<ImageInfoEntity> imageInfos = imageMapper
                        .selectBatchIds(taskVo.getImageIds())
                        .stream()
                        .peek(image -> image.setTaskId(taskId))
                        .collect(Collectors.toList());

                imageInfos.forEach(x -> imageMapper.updateById(x));
            }
            //向redis设置过期时间
            redisTemplate.opsForValue().set(key + taskId, String.valueOf(taskId), time, TimeUnit.SECONDS);
            log.info("设置redis过期时间成功，一共" + time + "秒");

            return R.ok("创建任务成功").put("taskId", taskId).put("validSeconds", time);
        } catch (RuntimeException e) {
            log.error(NAME + e.getMessage());
            return R.error("创建任务失败");
        }
    }

    private boolean checkEmpty(Object o) {
        return ObjectUtils.isEmpty(o);
    }

    @Override
    public R delete(String taskId) {
        try {
            this.removeById(Integer.parseInt(taskId));
            return R.ok("删除成功");
        } catch (RuntimeException e) {
            log.info(e.getMessage());
            return R.error("删除失败");
        }
    }

    @Override
    //@Cacheable("taskScreen")
    public List<TaskOverViewPo> getScreenTask(Map<String, String> conditions) {
        try {
            String categoryIdStr = conditions.get("categoryId");
            String pageNoStr = conditions.getOrDefault("pageNo", "1");
            String pageSizeStr = conditions.getOrDefault("pageSize", "10");
            String priceStartStr = conditions.getOrDefault("priceStart", "0.0");
            String priceEndStr = conditions.getOrDefault("priceEnd", "999999.0");

            Integer categoryId = Integer.parseInt(categoryIdStr);
            int pageSize = Integer.parseInt(pageSizeStr);
            Integer pageNo = (Integer.parseInt(pageNoStr) - 1) * pageSize;
            BigDecimal priceStart = new BigDecimal(priceStartStr);
            BigDecimal priceEnd = new BigDecimal(priceEndStr);


            PublishTaskMapper baseMapper = this.getBaseMapper();
            return baseMapper
                    .getScreenTask(categoryId, pageNo, pageSize, priceStart, priceEnd)
                    .stream()
                    .peek(x -> x.setImageUrls(getImageUrls(x.getId(), TASK)))
                    .collect(Collectors.toList());

        } catch (RuntimeException e) {
            log.error(NAME + e.getMessage());
            return null;
        }
    }

    @Override
    public Long getValidTime(String taskId) {
        TaskInfoEntity taskInfo = baseMapper.selectById(taskId);
        String expirationTime = taskInfo.getExpirationTime();
        String localDateTimeStr = LocalDateUtils.getLocalDateTimeStr();

        Long validSeconds = LocalDateUtils.getValidTimeSeconds(localDateTimeStr, expirationTime);
        if (ObjectUtils.isEmpty(validSeconds) || validSeconds <= 0) {
            return -1L;
        }
        return validSeconds;
    }

    @Override
    public R getTaskInfo(Integer taskId) {
        log.error(taskId + "");
        TaskInfoEntity taskInfo = this.getById(taskId);
        log.error(taskInfo.toString());
        if (ObjectUtils.isEmpty(taskInfo)) {
            return R.error("获取任务详情失败");
        }

        //添加用户浏览次数
        redisTemplate.opsForValue().increment("postCount:" + taskId, 1);
        Object count = redisTemplate.opsForValue().get("postCount:" + taskId);

        TaskDetailPo taskDetailPo = new TaskDetailPo();

        taskDetailPo.setViewCount(Integer.parseInt(String.valueOf(count)));
        BeanUtil.copyProperties(taskInfo, taskDetailPo);

        taskDetailPo.setImageUrls(getImageUrls(taskInfo.getId(), TASK));
        Integer userId = taskInfo.getUserId();
        UserEntity user = userMapper.selectById(userId);
        taskDetailPo.setUserName(user.getUserName());
        List<String> imageUrls = getImageUrls(userId, ImageIdType.USER);
        if (!ObjectUtils.isEmpty(imageUrls) && imageUrls.size() > 0) {
            taskDetailPo.setHeadUrl(imageUrls.get(0));
        }
        return R.ok().put("taskDetail", taskDetailPo);
    }

    /**
     * 任务发布者确认完成
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R confirmTask(Integer taskId) {

        //获取任务信息
        TaskInfoEntity taskInfo = this.getById(taskId);
        if (ObjectUtils.isEmpty(taskInfo)) {
            return R.error();
        }
        //获取订单信息
        QueryWrapper<OrderInfoEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("task_id", taskId);
        wrapper.eq("status_id", 6);
        OrderInfoEntity orderInfo = acceptTaskMapper.selectOne(wrapper);
        if (ObjectUtils.isEmpty(orderInfo)) {
            return R.error();
        }

        if (!taskInfo.getStatusId().equals(ORDER_CONFIRM.getId()) ||
                !taskInfo.getStatusId().equals(orderInfo.getStatusId())) {
            return R.error();
        }

        taskInfo.setStatusId(ORDER_COMPLETION.getId());
        orderInfo.setStatusId(ORDER_COMPLETION.getId());

        BigDecimal taskPrice = taskInfo.getTaskPrice();
        UserEntity user = userMapper.selectById(orderInfo.getUserId());
        BigDecimal balance = user.getBalance();
        user.setBalance(balance.add(taskPrice));

        //更新信息
        boolean b = this.updateById(taskInfo);
        int id = acceptTaskMapper.updateById(orderInfo);
        int i = userMapper.updateById(user);

        if (i <= 0 || !b || id <= 0) {
            return R.error();
        }
        return R.ok();
    }

    @Override
    public List<TaskOverViewPo> searchTask(String taskName) {
        List<TaskOverViewPo> task = this.baseMapper.searchTask(taskName);
        task.forEach(x -> x.setImageUrls(getImageUrls(x.getId(), TASK)));
        return task;
    }


    private List<String> getImageUrls(Integer id, ImageIdType idType) {
        return getStrings(id, imageMapper, idType);
    }
}
